library(tidyverse)
library(plotly)

theme_set(theme_minimal())

transitions <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2023/2023-03-28/transitions.csv')
Rows: 37284 Columns: 6── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): zone, begin, end, abbreviation
dbl (1): offset
lgl (1): dst
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
timezones <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2023/2023-03-28/timezones.csv')
Rows: 337 Columns: 4── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): zone, comments
dbl (2): latitude, longitude
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
timezone_countries <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2023/2023-03-28/timezone_countries.csv')
Rows: 428 Columns: 2── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): zone, country_code
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
countries <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2023/2023-03-28/countries.csv')
Rows: 240 Columns: 2── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): country_code, place_name
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
world_coordinates <- map_data("world")
current_transition <- transitions |>
  filter(begin <= '2023-03-30'  , end >= '2023-03-30' ) |>
  mutate(hour_offset = offset/3600) 
combined_timezones <- timezone_countries |>
  left_join(timezones , by='zone') |>
  left_join(countries , by='country_code') |>
  left_join(current_transition , by='zone') |>
  mutate(comments = ifelse(is.na(comments) , '' , comments) , 
         abbev = ifelse(substr(abbreviation , 0 ,1) %in% c('-' , '+' , '0') , '' , abbreviation ) , 
         daylight = ifelse(dst == 'TRUE' , 'DST' , ' '))
  
# geo styling
g <- list(
  scope = 'world',
  projection = list(type = 'robinson'),
  framecolor = 'dodgerblue',
  showland = TRUE,
  showocean = TRUE,
  showcountries = TRUE,
  landcolor = '#35CE8D',
  coastlinecolor = toRGB("white"),
  countrycolor = toRGB("white"),
  resolution = 50,
  lonaxis = list(showgrid = TRUE, dtick=10, gridcolor='black' , gridwidth=0.25)
  )

annot_dat <- data.frame(lat=0 , long=1 , 
                        text="<br><b>Data: </b>IANA tz database #TidyTuesday  <b>Map: </b>Nat Rivera @Itsnatrivera")

fig <- plot_geo(combined_timezones, lat = ~latitude, lon = ~longitude,  width = 900, height = 550) |> 
  add_markers( text = ~(paste(  paste0(zone , '   ' , daylight), place_name, 
                               paste0(abbev , '  Offset: ' , hour_offset) ,  
                               comments, sep = "<br>") ),  hoverinfo = "text" ,
               color = I('#4C4B63') , symbol = I("square"), size = I(6)  ) |> 
  add_annotations(data = annot_dat , y = ~lat, x = ~long , text = ~text , inherit = FALSE , showarrow = FALSE) |>
  layout(title = paste0('<br>' , '<b>Timezones Around the World</b><br>' , 'Markers are at Principal Locations'), 
         geo = g  )

 
fig
plt_map <- ggplot() +
  geom_map(data = world_coordinates, map = world_coordinates, aes(  long, lat, map_id = region ),
    color = "black", fill='#007500' ,  linewidth = 0.2) +
  geom_point(data=combined_timezones , aes(x=longitude, y=latitude) , color='dodgerblue' , show.legend = FALSE) +
  theme(
        panel.grid.major = element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        plot.caption = element_text()
    )
Warning: Ignoring unknown aesthetics: x and y
#p <- ggplotly(plt_map)
#p
#ggplotly(plt_map)
plt_map

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShwbG90bHkpCgp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQoKYGBgCgoKCgpgYGB7cn0KCnRyYW5zaXRpb25zIDwtIHJlYWRyOjpyZWFkX2NzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDIzLzIwMjMtMDMtMjgvdHJhbnNpdGlvbnMuY3N2JykKdGltZXpvbmVzIDwtIHJlYWRyOjpyZWFkX2NzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDIzLzIwMjMtMDMtMjgvdGltZXpvbmVzLmNzdicpCnRpbWV6b25lX2NvdW50cmllcyA8LSByZWFkcjo6cmVhZF9jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvbWFzdGVyL2RhdGEvMjAyMy8yMDIzLTAzLTI4L3RpbWV6b25lX2NvdW50cmllcy5jc3YnKQpjb3VudHJpZXMgPC0gcmVhZHI6OnJlYWRfY3N2KCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L21hc3Rlci9kYXRhLzIwMjMvMjAyMy0wMy0yOC9jb3VudHJpZXMuY3N2JykKCgp3b3JsZF9jb29yZGluYXRlcyA8LSBtYXBfZGF0YSgid29ybGQiKQpgYGAKCgoKYGBge3J9CmN1cnJlbnRfdHJhbnNpdGlvbiA8LSB0cmFuc2l0aW9ucyB8PgogIGZpbHRlcihiZWdpbiA8PSAnMjAyMy0wMy0zMCcgICwgZW5kID49ICcyMDIzLTAzLTMwJyApIHw+CiAgbXV0YXRlKGhvdXJfb2Zmc2V0ID0gb2Zmc2V0LzM2MDApIApgYGAKCgpgYGB7cn0KY29tYmluZWRfdGltZXpvbmVzIDwtIHRpbWV6b25lX2NvdW50cmllcyB8PgogIGxlZnRfam9pbih0aW1lem9uZXMgLCBieT0nem9uZScpIHw+CiAgbGVmdF9qb2luKGNvdW50cmllcyAsIGJ5PSdjb3VudHJ5X2NvZGUnKSB8PgogIGxlZnRfam9pbihjdXJyZW50X3RyYW5zaXRpb24gLCBieT0nem9uZScpIHw+CiAgbXV0YXRlKGNvbW1lbnRzID0gaWZlbHNlKGlzLm5hKGNvbW1lbnRzKSAsICcnICwgY29tbWVudHMpICwgCiAgICAgICAgIGFiYmV2ID0gaWZlbHNlKHN1YnN0cihhYmJyZXZpYXRpb24gLCAwICwxKSAlaW4lIGMoJy0nICwgJysnICwgJzAnKSAsICcnICwgYWJicmV2aWF0aW9uICkgLCAKICAgICAgICAgZGF5bGlnaHQgPSBpZmVsc2UoZHN0ID09ICdUUlVFJyAsICdEU1QnICwgJyAnKSkKICAKYGBgCgoKCgoKYGBge3J9CiMgZ2VvIHN0eWxpbmcKZyA8LSBsaXN0KAogIHNjb3BlID0gJ3dvcmxkJywKICBwcm9qZWN0aW9uID0gbGlzdCh0eXBlID0gJ3JvYmluc29uJyksCiAgZnJhbWVjb2xvciA9ICdkb2RnZXJibHVlJywKICBzaG93bGFuZCA9IFRSVUUsCiAgc2hvd29jZWFuID0gVFJVRSwKICBzaG93Y291bnRyaWVzID0gVFJVRSwKICBsYW5kY29sb3IgPSAnIzM1Q0U4RCcsCiAgY29hc3RsaW5lY29sb3IgPSB0b1JHQigid2hpdGUiKSwKICBjb3VudHJ5Y29sb3IgPSB0b1JHQigid2hpdGUiKSwKICByZXNvbHV0aW9uID0gNTAsCiAgbG9uYXhpcyA9IGxpc3Qoc2hvd2dyaWQgPSBUUlVFLCBkdGljaz0xMCwgZ3JpZGNvbG9yPSdibGFjaycgLCBncmlkd2lkdGg9MC4yNSkKICApCgphbm5vdF9kYXQgPC0gZGF0YS5mcmFtZShsYXQ9MCAsIGxvbmc9MSAsIAogICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PSI8YnI+PGI+RGF0YTogPC9iPklBTkEgdHogZGF0YWJhc2UgI1RpZHlUdWVzZGF5ICA8Yj5NYXA6IDwvYj5OYXQgUml2ZXJhIEBJdHNuYXRyaXZlcmEiKQoKZmlnIDwtIHBsb3RfZ2VvKGNvbWJpbmVkX3RpbWV6b25lcywgbGF0ID0gfmxhdGl0dWRlLCBsb24gPSB+bG9uZ2l0dWRlLCAgd2lkdGggPSA5MDAsIGhlaWdodCA9IDU1MCkgfD4gCiAgYWRkX21hcmtlcnMoIHRleHQgPSB+KHBhc3RlKCAgcGFzdGUwKHpvbmUgLCAnICAgJyAsIGRheWxpZ2h0KSwgcGxhY2VfbmFtZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoYWJiZXYgLCAnICBPZmZzZXQ6ICcgLCBob3VyX29mZnNldCkgLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21tZW50cywgc2VwID0gIjxicj4iKSApLCAgaG92ZXJpbmZvID0gInRleHQiICwKICAgICAgICAgICAgICAgY29sb3IgPSBJKCcjNEM0QjYzJykgLCBzeW1ib2wgPSBJKCJzcXVhcmUiKSwgc2l6ZSA9IEkoNikgICkgfD4gCiAgYWRkX2Fubm90YXRpb25zKGRhdGEgPSBhbm5vdF9kYXQgLCB5ID0gfmxhdCwgeCA9IH5sb25nICwgdGV4dCA9IH50ZXh0ICwgaW5oZXJpdCA9IEZBTFNFICwgc2hvd2Fycm93ID0gRkFMU0UpIHw+CiAgbGF5b3V0KHRpdGxlID0gcGFzdGUwKCc8YnI+JyAsICc8Yj5UaW1lem9uZXMgQXJvdW5kIHRoZSBXb3JsZDwvYj48YnI+JyAsICdNYXJrZXJzIGFyZSBhdCBQcmluY2lwYWwgTG9jYXRpb25zJyksIAogICAgICAgICBnZW8gPSBnICApCgogCmZpZwpgYGAKCgoKCgoKCmBgYHtyfQpwbHRfbWFwIDwtIGdncGxvdCgpICsKICBnZW9tX21hcChkYXRhID0gd29ybGRfY29vcmRpbmF0ZXMsIG1hcCA9IHdvcmxkX2Nvb3JkaW5hdGVzLCBhZXMoICBsb25nLCBsYXQsIG1hcF9pZCA9IHJlZ2lvbiApLAoJY29sb3IgPSAiYmxhY2siLCBmaWxsPScjMDA3NTAwJyAsICBsaW5ld2lkdGggPSAwLjIpICsKICBnZW9tX3BvaW50KGRhdGE9Y29tYmluZWRfdGltZXpvbmVzICwgYWVzKHg9bG9uZ2l0dWRlLCB5PWxhdGl0dWRlKSAsIGNvbG9yPSdkb2RnZXJibHVlJyAsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICB0aGVtZSgKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KCkKICAgICkKCiNwIDwtIGdncGxvdGx5KHBsdF9tYXApCiNwCiNnZ3Bsb3RseShwbHRfbWFwKQpwbHRfbWFwCmBgYAoKCgoKCgoKCgoKCgoKCgo=